// WebSocket信息交互对象
import { getUserFriendApplyRecord, refreshLastRead } from '../api/cache'
import { uuid } from './tool'
import { ElMessage } from 'element-plus'
import { Store } from 'vuex'
import { Router } from 'vue-router'
import {
  ApplyP2PCall,
  ResponseP2PCall,
  DescriptionP2PCall,
  NotifyFrameBuilt,
  IceP2PCall
} from './P2PCall'
import { ApplyCallUser, LoginUser } from './IpcData'

const { ipcRenderer } = require('electron')

// WebSocket状态
const ALIVE = 'ALIVE'
const SEND_MSG = 'SendMsg'
const SEND_MSG_SUCCESS = 'sendMsgSuccess'
const RECEIVE_MSG = 'receiveMsg'
const APPLY_FRIEND = 'applyFriend'
const RECEIVE_APPLY_FRIEND = 'receiveApplyFriend'
const RESP_FRIEND = 'respFriend'
const RECEIVE_RESP_FRIEND = 'receiveRespFriend'

// 通话业务
const APPLY_P2P_CALL = 'applyP2PCall'
const RECEIVE_APPLY_P2P_CALL = 'receiveApplyP2PCall'
const RESP_P2P_CALL = 'respP2PCall'
const RECEIVE_RESP_P2P_CALL = 'receiveRespP2PCall'
const NOTIFY_P2P_FRAME_BUILT = 'notifyP2PFrameBuilt'
const RECEIVE_P2P_FRAME_BUILT = 'receiveP2PFrameBuilt'
const SEND_P2P_CALL_ICE = 'sendP2PCallIce'
const RECEIVE_P2P_CALL_ICE = 'receiveP2PCallIce'
const SEND_P2P_CALL_OFFER = 'sendP2PCallOffer'
const RECEIVE_P2P_CALL_OFFER = 'receiveP2PCallOffer'
const SEND_P2P_CALL_ANSWER = 'sendP2PCallAnswer'
const RECEIVE_P2P_CALL_ANSWER = 'receiveP2PCallAnswer'
const CALL_P2P_REMOTE_DISCONNECT = 'callP2PRemoteDisconnect'
const RECEIVE_P2P_CALL_REMOTE_DISCONNECT = 'receiveP2PCallRemoteDisconnect'

const LOGOUT = 'logout'

// WebSocket传输对象
class WebSocketMsg {
  constructor(
    public sendType: string,
    public data: any
  ) {}

  toJSON() {
    return JSON.stringify({ sendType: this.sendType, data: this.data })
  }
}

// 消息对象
class Message {
  constructor(
    public msgId: string,
    public msgType: string,
    public sender: number,
    public receiver: number,
    public content: string
  ) {}
}

// 好友申请响应对象
class Friend {
  constructor(
    public applier: number,
    public receiver: number,
    public status: string
  ) {}
}

let socket: WebSocket | null = null

export function connectWebSocket(userId: number, store: Store<any>, router: Router) {
  // WebSocket通信
  // socket = new WebSocket('ws://127.0.0.1:7888/ws?userId=' + userId)
  socket = new WebSocket('ws://192.168.192.195:7888/ws?userId=' + userId)
  console.log('正在连接至Websocket服务器中...')

  socket.onopen = function () {
    console.log('WebSocket连接已建立')
    const msg = new WebSocketMsg(ALIVE, null)
    if (socket) socket.send(msg.toJSON())

    getUserFriendApplyRecord(userId).then((res: any) => {
      store.commit('SET_FRIEND_NOTIFICATION', res.data)
    })

    // 每 10秒，定期发送心跳信息
    setInterval(() => {
      const msg = new WebSocketMsg(ALIVE, null)
      if (socket) socket.send(msg.toJSON())
    }, 10000)
  }

  // 接收消息
  socket.onmessage = function (event) {
    const message = event.data

    if (message !== 'pong') {
      const msgObj = JSON.parse(message)
      switch (msgObj.sendType) {
        case RECEIVE_MSG: {
          if (store.getters.getNavPath !== 'resent') {
            store.commit('SET_NEW_MESSAGE_NOTIFICATION', true)
          }
          if (msgObj.data.sender === store.getters.getChatUserId) {
            store.dispatch('GetChatMessageList', [
              store.getters.getChatUserId,
              store.getters.getUserId
            ])
            refreshLastRead(msgObj.data.id, store.getters.getUserId, store.getters.getChatMsgId)
          }
          store.dispatch('GetResentMessageList', [store.getters.getUserId])

          if (ipcRenderer) {
            ipcRenderer.send('load-new-msg-audio')
          }
          break
        }
        case RECEIVE_APPLY_FRIEND: {
          if (store.getters.getNavPath !== 'friend') {
            store.commit('SET_FRIEND_NOTIFICATION', true)
          }
          break
        }
        case RECEIVE_RESP_FRIEND: {
          // 更新好友列表
          store.dispatch('GetFriendList', [store.getters.getUserId])
          break
        }
        case SEND_MSG_SUCCESS: {
          store.dispatch('GetChatMessageList', [
            store.getters.getChatUserId,
            store.getters.getUserId
          ])
          store.dispatch('GetResentMessageList', [store.getters.getUserId])
          break
        }
        case RECEIVE_APPLY_P2P_CALL: {
          console.log('接收到对方的通话请求')
          const applyCall: ApplyP2PCall = msgObj.data
          store.commit('SET_NOTIFY_USER_ID', applyCall.userId)
          store.commit('SET_NOTIFY_NICKNAME', applyCall.nickname)
          store.commit('SET_NOTIFY_AVATAR', applyCall.avatar)
          store.commit('SET_NOTIFY_TYPE', applyCall.callType)

          ipcRenderer.send('create-communication-notify-window', [
            new ResponseP2PCall(applyCall.targetId, applyCall.userId, false, ''),
            new LoginUser(
              store.getters.getUserId,
              store.getters.getUserNickname,
              store.getters.getUserAvatar
            ),
            new ApplyCallUser(
              applyCall.userId,
              applyCall.nickname,
              applyCall.avatar,
              applyCall.callType
            )
          ])
          break
        }
        case RECEIVE_RESP_P2P_CALL: {
          console.log('接收到对方的请求响应')
          ipcRenderer.send('handle-p2p-call-response', msgObj.data)
          break
        }
        case RECEIVE_P2P_FRAME_BUILT: {
          console.log('对方可以接收offer和ice')
          ipcRenderer.send('receive-p2p-frame-built')
          break
        }
        case RECEIVE_P2P_CALL_ICE: {
          console.log('接收到对方的ICE')
          ipcRenderer.send('receive-p2p-call-ice', msgObj.data)
          break
        }
        case RECEIVE_P2P_CALL_OFFER: {
          console.log('接收到对方的OFFER')
          ipcRenderer.send('receive-p2p-call-offer', msgObj.data)
          break
        }
        case RECEIVE_P2P_CALL_ANSWER: {
          console.log('接收到对方的ANSWER')
          ipcRenderer.send('receive-p2p-call-answer', msgObj.data)
          break
        }
        case RECEIVE_P2P_CALL_REMOTE_DISCONNECT: {
          console.log('接收到断开')
          store.commit('FLUSH_ALL_VIDEO_CALL_DATA')
          ipcRenderer.send('call-local-p2p-disconnect')
          break
        }
        case LOGOUT: {
          ElMessage.error('有新的用户登录')
          if (socket && socket.readyState === 1) {
            socket.close()
          }
          break
        }
      }
    }
  }

  // 连接关闭事件
  socket.onclose = function (event) {
    console.log('WebSocket连接已关闭', event.code, event.reason)
    ipcRenderer.send('handle-disconnect-websocket')
    router.push('/')
  }
}

export function handleUserLogOut() {
  if (socket && socket.readyState === 1) {
    const msg = new WebSocketMsg(LOGOUT, null)
    socket.send(msg.toJSON())
  }
}

export function sendMsg(args, store: Store<any>) {
  if (socket && socket.readyState === 1) {
    const [msgId, msgType, uid, msg] = args
    if (msgId && msgType && uid && msg) {
      const socketMsg = new WebSocketMsg(
        SEND_MSG,
        new Message(msgId, msgType, store.getters.getUserId, uid, msg)
      )
      socket.send(socketMsg.toJSON())
    }
  }
}

// 好友申请
export function applyFriend(args, store: Store<any>) {
  if (socket && socket.readyState === 1) {
    const receiver = args
    if (receiver) {
      const socketMsg = new WebSocketMsg(
        APPLY_FRIEND,
        new Friend(store.getters.getUserId, receiver, '')
      )
      socket.send(socketMsg.toJSON())
    }
  }
}

// 好友申请响应
export function responseFriendApply(args, store: Store<any>) {
  if (socket && socket.readyState === 1) {
    const [applier, receiver, status] = args
    if (applier && receiver && status) {
      const socketMsg = new WebSocketMsg(RESP_FRIEND, new Friend(applier, receiver, status))
      socket.send(socketMsg.toJSON())
      store.dispatch('GetFriendList', [store.getters.getUserId])

      if (status === '1') {
        let msgId = ''
        store.dispatch('GetResentMessageList', [store.getters.getUserId])
        const resentMessageList = store.getters.getResentMessageList
        if (resentMessageList) {
          resentMessageList.forEach((label) => {
            if (label.userId === applier) {
              msgId = label.msgId
            }
          })
        }

        if (msgId) {
          const socketMsg = new WebSocketMsg(
            SEND_MSG,
            new Message(
              msgId,
              'text',
              store.getters.getUserId,
              applier,
              '我接收了你的好友请求，快一起聊天吧！'
            )
          )
          socket.send(socketMsg.toJSON())
        } else {
          const socketMsg = new WebSocketMsg(
            SEND_MSG,
            new Message(
              uuid(),
              'text',
              store.getters.getUserId,
              applier,
              '我接收了你的好友请求，快一起聊天吧！'
            )
          )
          socket.send(socketMsg.toJSON())
        }
        store.dispatch('GetResentMessageList', [store.getters.getUserId])
      }
    }
  }
}

// 申请通话
if (ipcRenderer) {
  ipcRenderer.on('apply-p2p-call', (_, args) => {
    if (socket && socket.readyState === 1) {
      const socketMsg = new WebSocketMsg(APPLY_P2P_CALL, args)
      socket.send(socketMsg.toJSON())
    }
  })
}

// 响应通话
if (ipcRenderer) {
  ipcRenderer.on('response-p2p-call', (_, args) => {
    if (socket && socket.readyState === 1) {
      const socketMsg = new WebSocketMsg(RESP_P2P_CALL, args)
      socket.send(socketMsg.toJSON())
    }
  })
  ipcRenderer.send('flush-all-notification-data')
}

// 通知发起方，可以传输信息
if (ipcRenderer) {
  ipcRenderer.on('notify-p2p-frame-built', (_, args) => {
    if (socket && socket.readyState === 1) {
      const socketMsg = new WebSocketMsg(NOTIFY_P2P_FRAME_BUILT, new NotifyFrameBuilt(args))
      socket.send(socketMsg.toJSON())
    }
  })
}

// 发送ICE
if (ipcRenderer) {
  ipcRenderer.on('send-p2p-ice', (_, args) => {
    const ice: IceP2PCall = JSON.parse(args)
    if (socket && socket.readyState === 1) {
      const socketMsg = new WebSocketMsg(SEND_P2P_CALL_ICE, ice)
      socket.send(socketMsg.toJSON())
    }
  })
}

// 发送Offer
if (ipcRenderer) {
  ipcRenderer.on('send-p2p-offer', (_, args) => {
    const offer: DescriptionP2PCall = JSON.parse(args)
    if (socket && socket.readyState === 1) {
      const socketMsg = new WebSocketMsg(SEND_P2P_CALL_OFFER, offer)
      socket.send(socketMsg.toJSON())
    }
  })
}

// 发送Answer
if (ipcRenderer) {
  ipcRenderer.on('send-p2p-answer', (_, args) => {
    const answer: DescriptionP2PCall = JSON.parse(args)
    if (socket && socket.readyState === 1) {
      const socketMsg = new WebSocketMsg(SEND_P2P_CALL_ANSWER, answer)
      socket.send(socketMsg.toJSON())
    }
  })
}

// 通知对方已断开连接
if (ipcRenderer) {
  ipcRenderer.on('call-p2p-remote-disconnect', (_, args) => {
    const res: NotifyFrameBuilt = args
    if (socket && socket.readyState === 1) {
      const socketMsg = new WebSocketMsg(CALL_P2P_REMOTE_DISCONNECT, res)
      socket.send(socketMsg.toJSON())
    }
  })
  ipcRenderer.send('flush-all-p2p-data')
}
